/*
 * FunctionLibrary.java
 * 
 */

package matchstiklib;

/**
 *
 * @author Jon Ludwig
 */
public class FunctionLibrary {

    //public static final int funcs = 5;
    
    /**
     * Linear
     */
    public static FPoint linear(FPoint p)
    {
        return p;
    }
    
    /**
     * Sinusoidal
     */
    public static FPoint sinusoidal(FPoint p)
    {
        p.x = Math.sin(p.x);
        p.y = Math.sin(p.y);
        return p;
    }
    
    /**
     * Spherical
     */
    public static FPoint spherical(FPoint p)
    {
        double r = p.r();
        
        p.x = p.x / (Math.pow(r, 2) + Double.MIN_VALUE);
        p.y = p.y / (Math.pow(r, 2) + Double.MIN_VALUE);
        return p;
    }
    
    /**
     * Swirl
     */
    public static FPoint swirl(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = r*Math.cos(theta+r);
        p.y = r*Math.sin(theta+r);
        return p;
    }
    
    /**
     * Horseshoe
     */
    public static FPoint horseshoe(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = r*Math.cos(2*theta);
        p.y = r*Math.sin(2*theta);
        return p;
    }
    
    /**
     * Polar
     */
    public static FPoint polar(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = theta / Math.PI;
        p.y = r - 1;
        return p;
    }
    
    /**
     * Handkerchief
     */
    public static FPoint handkerchief(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = r*Math.sin(theta+r);
        p.y = r*Math.cos(theta-r);
        return p;
    }
    
    /**
     * Heart
     */
    public static FPoint heart(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = r*Math.sin(theta*r);
        p.y = -r*Math.cos(theta*r);
        return p;
    }
    
    /**
     * Disc
     */
    public static FPoint disc(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = theta*Math.sin(Math.PI * r) / Math.PI;
        p.y = theta*Math.cos(Math.PI * r) / Math.PI;
        return p;
    }
    
    /**
     * Spiral
     */
    public static FPoint spiral(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = (Math.cos(theta) + Math.sin(r)) / (r + Double.MIN_VALUE);
        p.y = (Math.sin(theta) - Math.cos(r)) / (r + Double.MIN_VALUE);
        return p;
    }
    
    /**
     * Hyperbolic
     */
    public static FPoint hyperbolic(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = Math.sin(theta) / (r + Double.MIN_VALUE);
        p.y = Math.cos(theta) / (r + Double.MIN_VALUE);
        return p;
    }
    
    /**
     * Diamond
     */
    public static FPoint diamond(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = Math.sin(theta) * Math.cos(r);
        p.y = Math.cos(theta) * Math.sin(r);
        return p;
    }
    
    /**
     * Ex
     */
    public static FPoint ex(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        p.x = r*Math.pow(Math.sin(theta+r), 3);
        p.y = r*Math.pow(Math.cos(theta-r), 3);
        return p;
    }
    
    /**
     * Julia
     */
    public static FPoint julia(FPoint p)
    {
        double r = p.r();
        double theta = p.theta();
        
        double side = Math.random();
        if (side > 0.5)
            side = Math.PI;
        else
            side = 0;
        
        p.x = Math.sqrt(r) * Math.cos(theta/2 + side);
        p.y = Math.sqrt(r) * Math.sin(theta/2 + side);
        return p;
    }
    
    /**
     * Fisheye
     */
    public static FPoint fisheye(FPoint p)
    {
        double r = p.r();
        double m = (2*r) / (r+1);
        
        p.x = p.x * m;
        p.y = p.y * m;
        return p;
    }
    
    /**
     * Cosine
     */
    public static FPoint cosine(FPoint p)
    {
        p.x = Math.cos(Math.PI*p.x) * Math.cosh(p.y);
        p.y = -Math.sin(Math.PI*p.x) * Math.sinh(p.y);
        return p;
    }
    
    /*
    public static FPoint f0(FPoint p)
    {
        p.x = 0;
        p.y *= 0.16;
        
        return p;
    }
    
    public static FPoint f1(FPoint p)
    {
        p.x = 0.2*p.x - 0.26*p.y;
        p.y = 0.23*p.x + 0.22*p.y + 1.6;
        
        return p;
    }
    
    public static FPoint f2(FPoint p)
    {
        p.x = -0.15*p.x + 0.28*p.y;
        p.y = 0.26*p.x + 0.24*p.y + 0.44;
        
        return p;
    }
    
    public static FPoint f3(FPoint p)
    {
        p.x = 0.85*p.x + 0.04*p.y;
        p.y = -0.04*p.x + 0.85*p.y + 1.6;
        
        return p;
    }
    
    public static FPoint f4(FPoint p)
    {
        
        
        return p;
    }
    */
}
